package com.binarysoft.service.common.httpclient;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.pool.PoolStats;
import org.apache.http.util.EntityUtils;

import common.framework.dsb.AbstractServiceBean;
import common.framework.dsb.annotation.DSBService;
import common.framework.dsb.service.ServiceContext;
import common.framework.log.Logger;

@DSBService(name = "DSB/HttpClientService")
public class HttpClientServiceBean extends AbstractServiceBean implements HttpClientService {
	private CloseableHttpClient httpclient = null;
	private BasicCookieStore cookieStore = null;
	private PoolingHttpClientConnectionManager connManger = null;
	private boolean closeFlag = false;

	@Override
	public void start(ServiceContext serviceContext) throws Exception {
		super.start(serviceContext);
		serviceContext.loadConfigProperties("httpclient.properties");
		cookieStore = new BasicCookieStore();
		connManger = new PoolingHttpClientConnectionManager();
	    //最大连接数
	    connManger.setMaxTotal(Integer.parseInt(serviceContext.getProperty("httpclient_poolmaxtotal")));
		httpclient = HttpClients.custom().setConnectionManager(connManger)
										 .setDefaultCookieStore(cookieStore).build();
		new IdleConnectionMonitorThread(connManger).start();
	}

	@Override
	public void refresh() throws Exception {

	}

	@Override
	public void close() throws Exception {
		httpclient.close();
		httpclient = null;
		closeFlag = true;
	}

	@Override
	public String httpGet(String url, Parameter[] params) throws Exception {
		String encodedParams = encodeParameters(params);
		if(encodedParams != null && !encodedParams.equals(""))
		{
			if (-1 == url.indexOf("?")) {
				url += "?" + encodedParams;
			} else {
				url += "&" + encodedParams;
			}
		}
		Logger.log(Logger.LOW_LEVEL, url);

		HttpGet getMethod = new HttpGet(url);
		String reponseResult = null;
		try {
			HttpResponse response = httpclient.execute(getMethod);
			System.out.println(response.getStatusLine().toString());

			reponseResult = gerResponseBody(response);
		} finally {
			getMethod.releaseConnection();
		}
		return reponseResult;
	}

	@Override
	public String httpPost(String url, Parameter[] params) throws Exception {
		HttpPost postMethod = new HttpPost(url);
		String result = null;
		try {
			postMethod.setHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:23.0) Gecko/20100101 Firefox/23.0");
			postMethod.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
			postMethod.setHeader("Accept-Language", "en-US,en;q=0.5");
			postMethod.setHeader("Accept-Encoding", "gzip, deflate");
			postMethod.setHeader("Content-Type", "application/json");

			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			for (Parameter param : params) {
				nvps.add(new BasicNameValuePair(param.getName(), param.getValue()));
			}

			// add cookies
			// addCookies(postMethod, cookieList);
			// add form
			postMethod.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));

			HttpResponse response = httpclient.execute(postMethod);
			System.out.println(response.getStatusLine().toString());

			result = gerResponseBody(response);
			// System.out.println(reponseResult);
		} finally {
			postMethod.releaseConnection();
		}
		return result;
	}

	public static String encodeParameters(Parameter[] params) {
		StringBuffer buf = new StringBuffer();
		for (int j = 0; j < params.length; j++) {
			if (j != 0) {
				buf.append("&");
			}
			try {
				buf.append(URLEncoder.encode(params[j].getName(), "UTF-8")).append("=").append(URLEncoder.encode(params[j].getValue(), "UTF-8"));
			} catch (java.io.UnsupportedEncodingException neverHappen) {
			}
		}
		return buf.toString();
	}

	private static String gerResponseBody(HttpResponse response) throws Exception {
		String result = null;
		HttpEntity entity = response.getEntity();
		if (entity != null) {
			byte[] bytes = EntityUtils.toByteArray(entity);
			result = new String(bytes, "utf-8");
		}
		return result;
	}
	
	private class IdleConnectionMonitorThread extends Thread {

        private final HttpClientConnectionManager connMgr;

        public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
            super();
            this.setName("IdleHttpConnectionMonitorThread");
            this.connMgr = connMgr;
        }

        @Override
        public void run() {
            try {
                while (!closeFlag) {
                        // 关闭失效的连接
                        connMgr.closeExpiredConnections();
                        // 可选的, 关闭30分钟内不活动的连接
                        connMgr.closeIdleConnections(30 * 60, TimeUnit.SECONDS);
                        sleep(10 * 1000);
                }
            } catch (InterruptedException ex) {
                // terminate
            	Logger.printStackTrace(Logger.LOW_LEVEL, "", ex);
            }
        }
    }
	
	public PoolStats getPoolStats(){
		if(connManger == null)
			return null;
		return connManger.getTotalStats();
	}

	
	
}
